#include "sdio.h"


SD_HandleTypeDef hsd;
DMA_HandleTypeDef hdma_sdio;


#define BLOCK_SIZE              512
#define NUMBER_OF_BLOCKS        2
#define READ_WRITE_ADDR         0x00000000

uint8_t rData[BLOCK_SIZE * NUMBER_OF_BLOCKS] = {0};
uint8_t wData[BLOCK_SIZE * NUMBER_OF_BLOCKS] = {0};
HAL_SD_CardStateTypeDef sdCardState;

void MX_SDIO_SD_Init(void)
{
    hsd.Instance = SDIO;
    hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
    hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
    hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
    hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
    hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
    hsd.Init.ClockDiv = 5;
    if(HAL_SD_Init(&hsd) != HAL_OK)
    {
        Error_Handler();
    }
    //hsd.Init.ClockDiv = 2;
    //hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
    //hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
    if(HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    {
        Error_Handler();
    }

}


void HAL_SD_MspInit(SD_HandleTypeDef *sdHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(sdHandle->Instance == SDIO)
    {
        __HAL_RCC_SDIO_CLK_ENABLE();

        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOD_CLK_ENABLE();
        GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        hdma_sdio.Instance = DMA2_Channel4;
        hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
        hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
        hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
        hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
        hdma_sdio.Init.Mode = DMA_NORMAL;
        hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
        if(HAL_DMA_Init(&hdma_sdio) != HAL_OK)
        {
            Error_Handler();
        }

        /* Several peripheral DMA handle pointers point to the same DMA handle.
     Be aware that there is only one channel to perform all the requested DMAs. */
    /* Be sure to change transfer direction before calling
     HAL_SD_ReadBlocks_DMA or HAL_SD_WriteBlocks_DMA. */
        __HAL_LINKDMA(sdHandle, hdmarx, hdma_sdio);
        __HAL_LINKDMA(sdHandle, hdmatx, hdma_sdio);

        HAL_NVIC_SetPriority(SDIO_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(SDIO_IRQn);



    }
}

void HAL_SD_MSPDeInit(SD_HandleTypeDef *sdHandle)
{
    if(sdHandle->Instance == SDIO)
    {
        __HAL_RCC_SDIO_CLK_DISABLE();
        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8 | GPIO_PIN_12);
        HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
        
        HAL_DMA_DeInit(sdHandle->hdmarx);
        HAL_DMA_DeInit(sdHandle->hdmatx);

        HAL_NVIC_DisableIRQ(SDIO_IRQn);
    }
}



void SDIO_ReadWriteTest(void)
{
    uint16_t i = 0;
    HAL_SD_StateTypeDef sdInitStatus;
    uint8_t sdHandleStatus;
    for (i = 0; i < BLOCK_SIZE * NUMBER_OF_BLOCKS; i++)
    {
        rData[i] = 0xFF;
        wData[i] = 0xFF;
    }
    sdInitStatus = HAL_SD_GetState(&hsd);
    if(sdInitStatus != HAL_SD_STATE_READY)
    {
        return;
    }
    ST7735S_DrawFont_GBK16(0, 16, BLACK, YELLOW, "SD Init OK...");

    //sdHandleStatus = HAL_SD_Erase(&hsd, READ_WRITE_ADDR, READ_WRITE_ADDR + BLOCK_SIZE * NUMBER_OF_BLOCKS);
    //if (sdHandleStatus != HAL_OK)
    //{
     //   return;
    //}
    //sdCardState = HAL_SD_GetCardState(&hsd);
    //while (sdCardState != HAL_SD_CARD_STANDBY);
    //ST7735S_DrawFont_GBK16(0, 32, BLACK, YELLOW, "SD Erase OK...");
    sdHandleStatus = HAL_SD_WriteBlocks(&hsd, wData, READ_WRITE_ADDR, NUMBER_OF_BLOCKS, 10000);
    if (sdHandleStatus != HAL_OK)
    {
        return;
    }
    sdCardState = HAL_SD_GetCardState(&hsd);
    while (sdCardState != HAL_SD_CARD_STANDBY)
    {
        sdCardState = HAL_SD_GetCardState(&hsd);
    }
    ST7735S_DrawFont_GBK16(0, 48, BLACK, YELLOW, "SD Write OK...");
    

    sdHandleStatus = HAL_SD_ReadBlocks(&hsd, rData, READ_WRITE_ADDR, NUMBER_OF_BLOCKS, 1000);
    if (sdHandleStatus != HAL_OK)
    {
        return;
    }
    
    while (sdCardState != HAL_SD_CARD_READY)
    {
        sdCardState = HAL_SD_GetCardState(&hsd);
    }
    ST7735S_DrawFont_GBK16(0, 64, BLACK, YELLOW, "SD Read OK...");
    
    
    
    ST7735S_DrawFont_GBK16(0, 80, BLACK, YELLOW, "Read Data: [0]");
    ST7735S_DrawNum(0, 80, BLACK, YELLOW, rData[0]);
}